package com.fsnbigdata.service.impl;

import com.fsnbigdata.domain.*;
import com.fsnbigdata.repository.DocumentRepository;
import com.fsnbigdata.repository.TaxonomyRepository;
import com.fsnbigdata.repository.ZhKoppDocumentRepository;
import com.fsnbigdata.repository.ZhKoppRepository;
import com.fsnbigdata.service.api.ZhKoppService;
import com.fsnbigdata.util.ObjectNull;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


@Service
public class ZhKoppServiceImpl implements ZhKoppService {
    
    @Autowired
    private ZhKoppRepository zhKoppRepository;

    @Autowired
    private TaxonomyRepository taxonomyRepository;

    @Autowired
    private DocumentRepository documentRepository;

    @Autowired
    private ZhKoppDocumentRepository zhKoppDocumentRepository;
    
    @Override
    public Kopp findById(Long id) {
        ZhKopp zhKopp = zhKoppRepository.findOne(id);
        Set<Document> documents = new HashSet <Document>();
        List<ZhKoppDocument> zhKoppDocuments = zhKoppDocumentRepository.findAllByKoppId( zhKopp.getId() );
        if(zhKoppDocuments.size()>0){
            for(ZhKoppDocument zhKoppDocument:zhKoppDocuments){
                documents.add( documentRepository.getById( zhKoppDocument.getDocumentId() ) );
            }
        }
        documents.remove( null );
        if(documents.isEmpty()){
            documents = new HashSet <>(  );
        }
        Kopp kopp = new Kopp( zhKopp.getId(),zhKopp.getKingdom(),zhKopp.getPhylumn(),zhKopp.getT_class(),
                zhKopp.getT_order(),zhKopp.getFamily(),zhKopp.getKingdom_en(),zhKopp.getPhylumn_en(),
                zhKopp.getT_class_en(),zhKopp.getT_order_en(),zhKopp.getFamily_en(),zhKopp.getZ_name(),
                zhKopp.getName_en(),zhKopp.getZ_character(),zhKopp.getZ_origin(),zhKopp.getZ_biogeography(),
                zhKopp.getZ_worth(),zhKopp.getZ_biodiversity(),zhKopp.getZ_alien(),zhKopp.getInitial(),
                zhKopp.getAdd_time(),zhKopp.getCreator(),documents);
        return kopp;
    }
    
    @Override
    public List<ZhKopp> findAll() {
        return zhKoppRepository.findAll();
    }
    
    @Override
    @Transactional
    public Kopp save(Kopp entity,String name) {  //i是标记，记录是更新还是新增
        ZhKopp kopp = new ZhKopp(entity.getId(),entity.getKingdom(),entity.getPhylumn(),
                entity.getT_class(),entity.getT_order(),entity.getFamily(),entity.getKingdom_en(),
                entity.getPhylumn_en(),entity.getT_class_en(),entity.getT_order_en(),entity.getFamily_en(),
                entity.getZ_name(),entity.getName_en(),entity.getZ_character(),entity.getZ_origin(),
                entity.getZ_biogeography(),entity.getZ_worth(),entity.getZ_biodiversity(),
                entity.getZ_alien(),entity.getInitial(),entity.getAdd_time(),name);

        kopp = zhKoppRepository.save(kopp);
        zhKoppDocumentRepository.deleteByKoppId(kopp.getId());
        Set<Document> docs = entity.getDocs();
        if(docs==null){
            docs = new HashSet <>(  );
        }
        for(Document document:docs){
            Document doc = document;
            doc.setCreator( name );
            if(document.getId()==null){
                doc = documentRepository.save( document );
            }
            ZhKoppDocument zhKoppDocument = new ZhKoppDocument();
            zhKoppDocument.setKoppId( kopp.getId() );
            zhKoppDocument.setDocumentId( doc.getId() );
            zhKoppDocumentRepository.save( zhKoppDocument );
            }
        return entity;
    }
    
    @Override
    public ZhKopp update(ZhKopp zhKopp) {
        return zhKoppRepository.save(zhKopp);
    }
    
    /**
     * 删除一个
     *
     * @param id
     * @return
     */
    @Override
    @Transactional
    public Integer deleteOne(Long id) {
        Integer i = 1;
        try {
            zhKoppDocumentRepository.deleteByKoppId(id);
            zhKoppRepository.delete(id);
        } catch (Exception e) {
            i = 0;
            System.out.println(e.getMessage());
        }
        return i;
    }
    
    /**
     * 删除多个
     *
     * @param ids
     * @return
     */
    @Transactional
    @Override
    public Integer deleteMany(String ids) {
        String[] strings = ids.split(",");
        List<ZhKopp> zhKoppList = new ArrayList<>();
        for (Integer i = 0; i < strings.length; i++) {
            ZhKopp zhKopp = new ZhKopp();
            zhKopp.setId(Long.parseLong(strings[i]));
            zhKoppList.add(zhKopp);
        }
        try {
            zhKoppRepository.deleteInBatch(zhKoppList);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return 0;
        }
        return 1;
    }
    
    @Override
    public Page<ZhKopp> findByPageAndSize(String name,String creator, Pageable pageable) {
        
        Specification<ZhKopp> specification = new Specification<ZhKopp>() {
            @Override
            public Predicate toPredicate(Root<ZhKopp> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                Path<String> _name = root.get("z_name");
                Path<String> _creator = root.get("creator");
                Predicate _key = criteriaBuilder.like(_name, "%" + name + "%");
                Predicate _key1 = criteriaBuilder.like(_creator, "%" + creator + "%");

                if (StringUtils.isNotBlank(name)&&StringUtils.isNotBlank(creator)){
                    return criteriaBuilder.and(_key,_key1);
                }

                if (StringUtils.isNotBlank(name)){
                    return criteriaBuilder.and(_key);
                }

                if (StringUtils.isNotBlank(creator)){
                    return criteriaBuilder.and(_key1);
                }
                return criteriaBuilder.and();
            }
        };
        return zhKoppRepository.findAll(specification, pageable);
    }
    /**
     * 临时类
     */
    class ZhKoppTree{
        private Long id;
        private String name;
        private List<ZhKoppTree> children;

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public List <ZhKoppTree> getChildren() {
            return children;
        }

        public void setChildren(List <ZhKoppTree> children) {
            this.children = children;
        }
    }

//    @Override
//    public List<ZhKopp> findAllKing() {
//        return zhKoppRepository.findAllKing(  );
//    }

//    @Override
//    public List findByAllKing() {
//        List <ZhKoppTree> zhKoppTrees = new ArrayList <>();
//        List<ZhKopp> zhKopps = zhKoppRepository.findAllKing();
//        for(ZhKopp zhKopp:zhKopps){
//            ZhKoppTree tree = new ZhKoppTree();
//            tree.setId( zhKopp.getId() );
//            tree.setName( zhKopp.getName_en()+" "+zhKopp.getZ_name() );
//            tree.setChildren( new ArrayList <>(  ) );
//            zhKoppTrees.add( tree );
//        }
//        return zhKoppTrees;
//    }

//    @Override
//    public List queryByParent_id(long parent_id) {
//        List <ZhKoppTree> zhKoppTrees = new ArrayList <>();
//        List<ZhKopp> zhKopps = zhKoppRepository.findByParent_id(parent_id);
//        for(ZhKopp zhKopp:zhKopps){
//            ZhKoppTree tree = new ZhKoppTree();
//            tree.setId( zhKopp.getId() );
//            tree.setName( zhKopp.getName_en()+" "+zhKopp.getZ_name() );
//            tree.setChildren( new ArrayList <>(  ) );
//            zhKoppTrees.add( tree );
//        }
//        return zhKoppTrees;
//    }

    @Override
    public List<ZhKopp> queryByAlphabet(String initial) {
        return zhKoppRepository.queryByAlphabet(initial);
    }

    /**
     * 获取分类表的界、门、纲、目、科
     * @param kingdom
     * @param phylumn
     * @param t_class
     * @param t_order
     * @return
     */
    @Override
    public Object getTaxonomy(String kingdom, String phylumn, String t_class, String t_order) {
        if(t_order!=null&&!("".equals( t_order ))){
            return taxonomyRepository.getByTOrder( kingdom, phylumn, t_class, t_order );
        }
        if(t_class!=null&&!("".equals( t_class ))){
            return taxonomyRepository.findByTClass( kingdom,phylumn,t_class );
        }
        if(phylumn!=null&&!("".equals( phylumn ))){
            return taxonomyRepository.findAllByPhylumn( kingdom,phylumn );
        }
        if(kingdom!=null&&!("".equals( kingdom ))){
            return taxonomyRepository.findAllByKingdom( kingdom );
        }
        return taxonomyRepository.findAllByKingdomAndKingdomLatin();
    }

    /**
     * 获取科普前台的树
     * @param kingdom
     * @param phylumn
     * @param t_class
     * @param t_order
     * @return
     */
    @Override
    public List getTree(String kingdom, String phylumn, String t_class, String t_order) {
        //临时使用的内部类
        class NewTree {
            Long id;
            String name;

            public Long getId() {
                return id;
            }

            public void setId(Long id) {
                this.id = id;
            }

            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }
        }
        List<ZhKoppTree> trees = new ArrayList <>(  );
        List<Object> objects = new ArrayList <>(  );
        if(t_order!=null&&!("".equals( t_order ))&&objects.size()==0){
            List<NewTree> newTrees = new ArrayList <>();
            objects = zhKoppRepository.getByTOrder( kingdom, phylumn, t_class, t_order );
            for (Object o:objects){
                Object[] objects1 = (Object[]) o;
                if(objects1[1]!=null&&!("".equals( objects1[1] ))){
                    NewTree newTree = new NewTree();
                    newTree.setId( Long.parseLong( ""+objects1[0] ) );
                    newTree.setName( (ObjectNull.takeOutNull(objects1[1])+" "+ObjectNull.takeOutNull(objects1[2])).trim() );
                    newTrees.add( newTree );
                }
            }
            return newTrees;
        }

        if(t_class!=null&&!("".equals( t_class ))&&objects.size()==0){
            objects = zhKoppRepository.findByTClass( kingdom,phylumn,t_class );
        }
        if(phylumn!=null&&!("".equals( phylumn ))&&objects.size()==0){
            objects =  zhKoppRepository.findAllByPhylumn( kingdom,phylumn );
        }
        if(kingdom!=null&&!("".equals( kingdom ))&&objects.size()==0){
            objects =  zhKoppRepository.findAllByKingdom( kingdom );
        }else if(objects.size()==0) {
            objects = zhKoppRepository.findAllByKingdomAndKingdomLatin();
        }
        for (Object s:objects){
            Object[] objs = (Object[]) s;
            if(objs[1]!=null&&!("".equals( objs[1]+"" ))) {
                ZhKoppTree tree = new ZhKoppTree();
                tree.setId( Long.parseLong( ""+objs[0] ) );
                tree.setName( (ObjectNull.takeOutNull(objs[1])+" "+ObjectNull.takeOutNull(objs[2])).trim() );
                tree.setChildren( new ArrayList <>() );
                trees.add( tree );
            }
        }
        return trees;
    }

    @Override
    public Kopp getData(String kingdom, String phylumn, String t_class, String t_order, String z_name) {
        List<ZhKopp> zhKopps = zhKoppRepository.getData(kingdom,phylumn,t_class,t_order,z_name);
        if(zhKopps.size()==0){
            return null;
        }
        ZhKopp zhKopp = zhKopps.get( 0 );
        Set<Document> documents = new HashSet <Document>();
        List<ZhKoppDocument> zhKoppDocuments = zhKoppDocumentRepository.findAllByKoppId( zhKopp.getId() );
        if(zhKoppDocuments.size()>0){
            for(ZhKoppDocument zhKoppDocument:zhKoppDocuments){
                documents.add( documentRepository.getById( zhKoppDocument.getDocumentId() ) );
            }
        }
        documents.remove( null );
        if(documents.isEmpty()){
            documents = new HashSet <>(  );
        }
        Kopp kopp = new Kopp( zhKopp.getId(),zhKopp.getKingdom(),zhKopp.getPhylumn(),zhKopp.getT_class(),
                zhKopp.getT_order(),zhKopp.getFamily(),zhKopp.getKingdom_en(),zhKopp.getPhylumn_en(),
                zhKopp.getT_class_en(),zhKopp.getT_order_en(),zhKopp.getFamily_en(),zhKopp.getZ_name(),
                zhKopp.getName_en(),zhKopp.getZ_character(),zhKopp.getZ_origin(),zhKopp.getZ_biogeography(),
                zhKopp.getZ_worth(),zhKopp.getZ_biodiversity(),zhKopp.getZ_alien(),zhKopp.getInitial(),
                zhKopp.getAdd_time(),zhKopp.getCreator(),documents);
        return kopp;
    }

//    @Override
//    public List<ZhKopp> findByParent_id(long parent_id) {
//        return zhKoppRepository.findByParent_id(parent_id);
//    }
    
    @Override
    public void delete(Iterable<Long> ids) {
        List<ZhKopp> zhKopps = zhKoppRepository.findAll(ids);
        zhKoppRepository.deleteInBatch(zhKopps);
    }
    
}
